package pl.edu.agh.lab2.sr.playerClient;

import java.rmi.RemoteException;
import java.util.List;

import pl.edu.agh.lab2.sr.beans.Field;
import pl.edu.agh.lab2.sr.beans.GameMap;
import pl.edu.agh.lab2.sr.beans.GameResponses;
import pl.edu.agh.lab2.sr.beans.IPlayer;
import pl.edu.agh.lab2.sr.beans.InvalidGameStateException;
import pl.edu.agh.lab2.sr.beans.InvalidUserException;
import pl.edu.agh.lab2.sr.beans.Player;
import pl.edu.agh.lab2.sr.beans.ServerListener;
import pl.edu.agh.lab2.sr.remoteInterfaces.IBattleshipGame;
import pl.edu.agh.lab2.sr.remoteInterfaces.IGameServer;
import pl.edu.agh.lab2.sr.remoteInterfaces.IServerListener;

public class PlayerConsoleImpl {

	private IPlayer player;
	private IServerListener listener;
	private IGameServer server;
	private IBattleshipGame game;

	public PlayerConsoleImpl(IGameServer server, String nick)
			throws RemoteException {
		this.player = new Player(nick);
		this.listener = new ServerListener();
		this.server = server;
	}

	public void menuLoop() {
		while (true) {
			PlayerMenuCommands action = null;
			String command = null;
			try {
				command = System.console().readLine();
				action = PlayerMenuCommands.valueOf(command);
			} catch (IllegalArgumentException e) {
				System.out.println("Error, bad command: " + command
						+ ". Available:");
				for (PlayerMenuCommands a : PlayerMenuCommands.values()) {
					System.out.print(a.toString() + ", ");

				}
				System.out.println();
				continue;
			}
			try {
				switch (action) {
				case r:
				case register: {
					handleRegister();
					break;
				}
				case cp:
				case createWithPlayer: {
					handleCreateGame(false);
					break;
				}
				case cb:
				case createWithBot: {
					handleCreateGame(true);
					break;
				}
				case lg:
				case listGames: {
					handleListGames();
					break;
				}
				case j:
				case join: {
					handleJoinGame();
					break;
				}
				case lr:
				case listRegistered: {
					handleListRegisteredPlayers();
					break;
				}
				case exit: {
					handleMenuExit();
					break;
				}


				}
			} catch (Exception e) {
				System.out.println("[P] Error: " + e.toString());
			}

		}

	}

	public void handleRegister() throws RemoteException, InvalidUserException {
		server.register(player, listener);
		System.out.println("[P]: registered on server");
	}

	private void handleListRegisteredPlayers() throws RemoteException {
		List<String> playerNicks = server.getRegisteredPlayers();
		System.out.println("#Registered players: " + playerNicks.size());
		for (String nick : playerNicks) {
			System.out.println("   " + nick);
		}
	}

	private void handleCreateGame(boolean withBot) throws RemoteException,
			InvalidUserException, InvalidGameStateException {
		game = server.createBattleshipGame(player, listener, withBot);
		gameLoop();
	}

	private void handleListGames() throws RemoteException {
		List<String> gamesList = server.getGamesList();
		System.out.println("#Created games: " + gamesList.size());
		for (String game : gamesList) {
			System.out.println(game);
		}
	}

	private void handleJoinGame() throws RemoteException, InvalidUserException,
			IllegalArgumentException, InvalidGameStateException {
		System.out.println("type game id:");
		int id;
		try {
			id = Integer.parseInt(System.console().readLine());
		} catch (NumberFormatException e) {
			System.out.println("Bad number typed");
			return;
		}

		game = server.join(player, listener, id);
		System.out.println("P: joined game");
		gameLoop();
	}

	private void handleMenuExit() throws RemoteException, InvalidUserException {
		System.out.println("[P]: exit");
		server.quit(player, listener);
		System.exit(0);
	}

	public void gameLoop() {
		while (true) {
			PlayerGameCommands command = null;
			String commandStr = null;
			try {
				commandStr = System.console().readLine();
				command = PlayerGameCommands.valueOf(commandStr);
			} catch (IllegalArgumentException e) {
				System.out.println("Error, bad command: " + commandStr
						+ ". Available:");
				for (PlayerGameCommands a : PlayerGameCommands.values()) {
					System.out.print(a.toString() + ", ");

				}
				System.out.println();
				continue;
			}
			try {
				switch (command) {
				case i:
				case initMap: {
					handleInitMap();
					break;
				}
				case m:
				case move: {
					handleMove();
					break;
				}

				case a:
				case printAll: {
					handleShowStatus();
					handlePrintMap();
					break;
				}
				case s:
				case printStatus:{
					handleShowStatus();
					break;
				}
				case p:
				case printMap: {
					handlePrintMap();
					break;
				}

				case q:
				case quit: {
					handleQuitFromGame();
					break;
				}

				case start: {
					handleStartGame();
					break;
				}

				}
			} catch (Exception e) {
				System.out.println("[P] Error: " + e.toString());
			}

		}

	}

	private void handleInitMap() throws RemoteException, InvalidUserException {
		System.out.println("[P] initializing map");
		GameMap map = new GameMap();
		map.initMyMapWithSampleShips(player.getNick().length());
		game.initMap(player, map);

	}

	private void handleMove() throws RemoteException,
			InvalidGameStateException, InvalidUserException {
		Field field = getFieldFromConsole();
		GameResponses response = game.move(player, field);
		System.out.println("[P] response from server: " + response);
	}

	private Field getFieldFromConsole() {
		System.out.println("Type shot coordinates (e.g. J10):");
		String line = System.console().readLine().toUpperCase();
		if (!line.matches("[A-J]([1-9]|(10))")) {
			throw new IllegalArgumentException("Bad input: " + line);
		}
		char x = line.charAt(0);
		int y = Integer.parseInt(line.substring(1));
		Field field = new Field(x, y);
		return field;
	}

	public static void main(String[] args) {
		String line = "J10";
		if (!line.matches("[A-J]([1-9]|(10))")) {
			throw new IllegalArgumentException("Bad input: " + line);
		}

	}

	private void handlePrintMap() throws RemoteException, InvalidUserException {
		GameMap map = game.getMap(player);
		if (map != null) {
			System.out.println(map);
			System.out.println(map.getLegend());
		} else {
			System.out.println("Map not initialized");
		}
	}

	private void handleQuitFromGame() {
		// TODO Auto-generated method stub
	}

	private void handleStartGame() throws RemoteException,
			InvalidGameStateException, InvalidUserException {
		game.startGame(player);
	}

	private void handleShowStatus() throws RemoteException {
		String info = game.getInfoAboutGame();
		System.out.println("Current Game status:");
		System.out.println(info);
	}

}
